Lab setup

Start RStudio and open the egrid-lab-setup.R file.

Use the mouse to highlight all the code and press CTRL+ENTER or the Run button in the upper-right of the editor window.

These commands will load the necessary libraries, create a dataframe from the eGRID spreadsheet, select the important variables for the lab, and rename them for ease of use and understanding. You will already have run a copy of them in the egrid-lab-setup.R file.

knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.3     v dplyr   1.0.7
## v tidyr   1.1.3     v stringr 1.4.0
## v readr   2.0.0     v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(readxl)
library(sf)
## Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
library(tmap)

# sets working directory to R source file location
setwd("c:/temp/class0921")
message(paste0("Working directory = ", getwd()))
## Working directory = c:/temp/class0921
# loads custom functions
source("./functions/functions1a.R")

egrid1 = read_excel("./data/egrid2018_data_v2.xlsx",
                    sheet="PLNT18",skip=1) %>% 
         tolow2()

egrid2 = egrid1 %>% mutate(StateAbbr = pstatabb,
                           PlantName = pname,
                           NamePlateCapMW = namepcap,
                           Fuel = plfuelct,
                           NetGenGWh = plngenan/10^3,
                           CO2tonsm = replace_na(plco2eqa,0)/10^6) %>% 
  select(StateAbbr, PlantName, Fuel,
         NamePlateCapMW,
         NetGenGWh,
         CO2tonsm,
         lat,lon)

st2 = egrid2 %>% 
  filter(StateAbbr == "GA") %>% 
  filter(lat > 0 & lon < 0)
          
st3 = st2 %>% filter(NamePlateCapMW >= 1000)


st2geo = st_as_sf(st2, coords = c("lon", "lat"), 
                          crs = 4326) %>% 
  select(PlantName, everything())

stsolargeo = st2geo %>% 
  filter(Fuel == "SOLAR")

gacounty = st_read("./gisdata/gacounty.shp") %>% 
  select(NAME, everything())
## Reading layer `gacounty' from data source `C:\temp\class0921\gisdata\gacounty.shp' using driver `ESRI Shapefile'
## Simple feature collection with 159 features and 12 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XYZ
## Bounding box:  xmin: -85.60516 ymin: 30.35784 xmax: -80.84055 ymax: 35.00066
## z_range:       zmin: 0 zmax: 0
## Geodetic CRS:  NAD83
istates = st_read("./gisdata/interstates.shp")
## Reading layer `interstates' from data source 
##   `C:\temp\class0921\gisdata\interstates.shp' using driver `ESRI Shapefile'
## Simple feature collection with 689 features and 7 fields
## Geometry type: MULTILINESTRING
## Dimension:     XY
## Bounding box:  xmin: -158.0901 ymin: 21.27311 xmax: -67.78119 ymax: 64.88822
## Geodetic CRS:  WGS 84

eGRID

The focus of this lab is using ggplot2 for basic visualization of power plant level electricity and CO2 emissions data from the EPA eGRID dataset. eGRID stands for “Emissions & Generation Resource Integrated Database” and is available from

https://www.epa.gov/egrid

Initial code from above has already loaded the 2018 EPA Egrid dataset from the egrid2018_data_v2.xlsx spreadsheet. That spreadsheet is located in a subdirectory named “data” one level down from your working directory. Throughout the course we will store input data in its own folder so we can easily find it and update it whenever new data becomes available. As long as the data format has not changed, our R code should work exactly the same way with the updated data.

The setup code has also selected a subset of varibles and renamed them for convenience, and created two additional datasets:

st2 has only Georgia power plants st3 has only large (over 1.0 GW) Georgia power plants

Type each of the following commands into the console to confirm your current working directory and explore basic information about the st3 dataset:

getwd()
## [1] "C:/courses/cca/class0921"
summary(st3)
##   StateAbbr          PlantName             Fuel           NamePlateCapMW
##  Length:12          Length:12          Length:12          Min.   :1099  
##  Class :character   Class :character   Class :character   1st Qu.:1342  
##  Mode  :character   Mode  :character   Mode  :character   Median :1734  
##                                                           Mean   :2220  
##                                                           3rd Qu.:3287  
##                                                           Max.   :4520  
##                                                                         
##    NetGenGWh           CO2tonsm             lat             lon        
##  Min.   :   92.23   Min.   : 0.00000   Min.   :31.93   Min.   :-85.04  
##  1st Qu.: 4066.98   1st Qu.: 0.05145   1st Qu.:33.12   1st Qu.:-84.94  
##  Median : 9053.31   Median : 2.85259   Median :33.38   Median :-84.69  
##  Mean   : 9755.88   Mean   : 4.49050   Mean   :33.33   Mean   :-83.89  
##  3rd Qu.:14912.00   3rd Qu.: 4.53004   3rd Qu.:33.55   3rd Qu.:-83.06  
##  Max.   :19959.13   Max.   :18.39730   Max.   :34.71   Max.   :-81.18  
##  NA's   :1
head(st3)
glimpse(st3)
## Rows: 12
## Columns: 8
## $ StateAbbr      <chr> "GA", "GA", "GA", "GA", "GA", "GA", "GA", "GA", "GA", "~
## $ PlantName      <chr> "Bowen", "Edwin I Hatch", "Harllee Branch", "Jack McDon~
## $ Fuel           <chr> "COAL", "NUCLEAR", "COAL", "GAS", "GAS", "COAL", "GAS",~
## $ NamePlateCapMW <dbl> 3540.4, 1721.8, 1746.2, 3202.0, 1376.6, 3564.0, 1099.2,~
## $ NetGenGWh      <dbl> 13619.914, 14403.550, NA, 16799.053, 9053.313, 15420.44~
## $ CO2tonsm       <dbl> 14.78503521, 0.00000000, 0.00000000, 6.82052236, 3.7665~
## $ lat            <dbl> 34.12560, 31.93420, 33.19500, 33.82390, 32.34780, 33.06~
## $ lon            <dbl> -84.92220, -82.34470, -83.29830, -84.47580, -81.18170, ~
View(st3)

Remember:

NamePlateCapMW: nameplate plant capacity in megawatts of power

NetGenGWh: annual net generation in gigawatt-hours of energy

Customary and SI (Metric) terms for large numbers

You’ll just have to memorize these.

Large number abbreviations

For reference, in 2019 Georgia retail electricity sales were

For a state population of 10.6 million, that’s about 13 MWh per person

Mapping eGRID

We can use tmap to visualize electricity generation across Georgia:

tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(gacounty) +
  tm_polygons(col="palegreen") +
tm_shape(istates) +
  tm_lines(col="tomato4") +
tm_shape(st2geo) +
  tm_dots("Fuel", size="NetGenGWh")
## Legend for symbol sizes not available in view mode.

Since solar plants are relatively small compared to large conventional plants, this map shows only solar:

tm_shape(gacounty) +
  tm_polygons(col="palegreen") +
tm_shape(istates) +
  tm_lines(col="tomato4") +
tm_shape(stsolargeo) +
  tm_dots(col="yellow",size="NetGenGWh")
## Legend for symbol sizes not available in view mode.

Power, Energy, and Capacity Factors

My Speedometer

What is the speed nameplate capacity of my 2002 Toyota Camry? What’s the 220 number near the 140? Does the top speed of my Camry care whether it’s measured in miles per hour, kilometers per hour, or feet per second?

See below for a real solar panel nameplate.

Solar Panel Nameplate

Basic energy/heat/work units:

One Joule (metric): the work done by a force of one newton when its point of application moves one meter

One BTU (British thermal unit, Customary): amount of heat required to raise the temperature of one pound of water by one degree.

Sidenote 1: 1 BTU = 1055 Joules. In the US we use BTUs as the basic unit of energy/heat/work.

Sidenote 2: energy, heat, and work are all measured in energy units. See figures below for electricity transformed into heat and work.

Electricity transformed into heat

Electricity transformed into work

Power units for electricity

For electricity generation, power is the generator’s output in terms of Watts. One Watt is one joule of energy delivered in one second. It is a rate, similar to speed in miles per hour. For electricity generation power is important since the electricity system’s input power (in Watts generated) must always match quite closely the system’s output (in Watts consumed).

Energy units for electricity

For electricity generation, energy is the accumulated power over a specific period of time. One kilowatt-hour is equal to one kilowatt of power (about one microwave oven, or ten traditional 100-watt lightbulbs) delivered over one hour. For climate change, we must measure energy consumed in the generation of electricity (sadly in customary BTU units rather than metric joules) to calculate the amount of CO2 released.

Note: 1 kWh in energy is equal to 3412.14 BTUs of energy

Capacity factors

A capacity factor is the ratio of an electricity generator’s actual monthly or annual electrical energy produced divided by its maximum nameplate energy output for the same period.

Use the View(st3) command to find the nameplate capacity of Plant Hatch (in megawatts) and its actual 2018 output in gigawatt-hours. Then carry out the calculations shown below to calculate Plant Hatch’s capacity factor.

# View(st3)
# Plant Hatch (nuclear)

actualgwh = 14404
npcapacitymw = 1722
# convert MW to GW
npcapacitygw = npcapacitymw / 10^3
# find output if run 24 hours per day 365.25 days per year
npoutputgwh = npcapacitygw * 24 * 365.25
# calculate ratio of actual output to nameplate output
capacityfactor = actualgwh / npoutputgwh
print(capacityfactor)
## [1] 0.95422

Over one year what percentage of the time is Plant Hatch producing electricity?

Why do utilities tend to run nuclear plants (almost) all the time?

Now conduct similar calculations for Plant Sherer (coal).

actualgwh = 15420
npcapacitymw = 3564

npcapacitygw = npcapacitymw / 10^3

npoutputgwh = npcapacitygw * 24 * 365.25

capacityfactor = actualgwh / npoutputgwh
print(capacityfactor)
## [1] 0.493566

Why less than 50%? What electricity energy source is gradually pushing out coal?

Utility-scale solar farms in Georgia

stsolar = st2 %>% filter(Fuel=="SOLAR")

ggplot(data=stsolar, aes(x=NamePlateCapMW,y=NetGenGWh,color=Fuel)) +
  geom_point(size=3) +
  geom_text(aes(label=PlantName,color=Fuel,
                hjust=1,vjust=1))
## Warning: Removed 25 rows containing missing values (geom_point).
## Warning: Removed 25 rows containing missing values (geom_text).

 ggplot(data=stsolar, aes(x=NamePlateCapMW,y=NetGenGWh,color=Fuel)) +
  geom_point(size=3) +
  geom_smooth(aes(x=NamePlateCapMW,y=NetGenGWh,col=Fuel),
              method=lm,se=FALSE)
## `geom_smooth()` using formula 'y ~ x'
## Warning: Removed 25 rows containing non-finite values (stat_smooth).
## Warning: Removed 25 rows containing missing values (geom_point).

  geom_text(aes(label=PlantName,color=Fuel,
                hjust=1,vjust=1))
## mapping: label = ~PlantName, colour = ~Fuel, hjust = 1, vjust = 1 
## geom_text: parse = FALSE, check_overlap = FALSE, na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_identity

Capacity factor calculations for Taylor County Solar

# View(st3) or #View(stsolar)

actualgwh = 288.968
npcapacitymw = 148

npcapacitygw = npcapacitymw / 10^3

npoutputgwh = npcapacitygw * 24 * 365.25

capacityfactor = actualgwh / npoutputgwh
print(capacityfactor)
## [1] 0.222734

Side note: are you tired of entering the capacity factor calculation? Wouldn’t it be great if we could “package” that calculation, enter two numbers, and pop out the answer?

The following command fits a regression line to the solar data

summary(lm(data=stsolar, NetGenGWh ~ NamePlateCapMW))
## 
## Call:
## lm(formula = NetGenGWh ~ NamePlateCapMW, data = stsolar)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -13.4555  -2.7992   0.6757   1.5467  19.0484 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    -1.69881    1.14694  -1.481    0.146    
## NamePlateCapMW  2.02211    0.02847  71.034   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.073 on 41 degrees of freedom
##   (25 observations deleted due to missingness)
## Multiple R-squared:  0.9919, Adjusted R-squared:  0.9917 
## F-statistic:  5046 on 1 and 41 DF,  p-value: < 2.2e-16

Conclusion from the regression: in planning for utility-scale solar in Georgia we can take the MW nameplate capacity of the installation and double it to calculate the number of GWh delivered over a year.

From earlier: Georgia consumes 139,301 GWh of electricity per year. Assume, in the future, 45% of that electricity will be generated by nuclear, leaving 76616 GWh that we would like to be generated by future solar PV farms. . How many 150 MW solar farms (the size of the Taylor County farm, the largest currently in Georgia) would we need to meet the future demand for electricity? How many would we need to construct per year to meet Biden’s goal of zero-carbon electricity by 2035?

The Taylor County solar farm (146 MW nameplate capacity) covers 911 acres.

How many acres of land are required to build 1 GWh of solar energy output in Georgia?

How many square miles (at 640 acres per square mile) will it take to deliver 77000 GWh of solar electricity?

Don’t look below until you’ve done the calculation, but here are the steps

For reference, the city of Atlanta is 136 square miles.